
use anyhow::{anyhow, Result};

use hyper::{Client, client::HttpConnector};

use serde_json::Value;

use crate::rpc::{JsonRpcRequest, jsonrpc_request};

pub async fn sector_ticket_height(client: &Client<HttpConnector>, url: &str, token: &str, sector: u64, miner: &str) -> Result<u64> {
    let request = JsonRpcRequest {
        id: 1,
        jsonrpc: "2.0".to_owned(),
        method: "Filecoin.StateSectorPreCommitInfo".to_owned(),
        params: vec![Value::String(miner.to_string()), Value::from(sector), Value::Array(vec![])]
    };
    let value = jsonrpc_request::<Value>(client, url, token, request).await;
    match value {
        Err(e) => Err(e),
        Ok(v) => {
            let v = v.unwrap();
            let p = v.pointer("/Info/SealRandEpoch");
            if p.is_none() {
                return Err(anyhow!("Height not found. response: {}", v.to_string()))
            }
            let h = p.unwrap();
            if let Value::Number(n) = h {
                let height = n.as_u64();
                if height.is_none() {
                    return Err(anyhow!("Height not found. none. response: {}", v.to_string()))
                }
                log::info!("find height for sector {}: {:?}", sector, height);
                return Ok(height.unwrap())
            }
            return Err(anyhow!("wrong response: {}", v.to_string()))
        }
    }
}

pub async fn chain_height_tipset(client: &Client<HttpConnector>, url: &str, token: &str, height: u64) -> Result<Vec<Value>> {
    let request = JsonRpcRequest {
        id: 1,
        jsonrpc: "2.0".to_owned(),
        method: "Filecoin.ChainGetTipSetByHeight".to_owned(),
        params: vec![Value::from(height), Value::Array(vec![])]
    };
    let value = jsonrpc_request::<Value>(client, url, token, request).await;
    match value {
        Err(e) => Err(e),
        Ok(v) => {
            let v = v.unwrap();
            let p = v.pointer("/Cids");
            if p.is_none() {
                return Err(anyhow!("Cids not found. response: {}", v.to_string()))
            }
            let h = p.unwrap();
            if let Value::Array(n) = h {
                let key = n.clone();
                log::info!("find key for height {}: {}", height, key.len());
                return Ok(key)

            }
            return Err(anyhow!("wrong response: {}", v.to_string()))
        }
    }
}

pub async fn sector_randomness(client: &Client<HttpConnector>, url: &str, token: &str, height: u64, miner: &str, key: Vec<Value>) -> Result<String> {
    // f0705937
    let v = vec![68u8, 0, 145, 139, 43];

    let request = JsonRpcRequest {
        id: 1,
        jsonrpc: "2.0".to_owned(),
        method: "Filecoin.StateGetRandomnessFromTickets".to_owned(),
        params: vec![Value::from(5u8), Value::from(height), Value::from(v), Value::from(key)]
    };
    let value = jsonrpc_request::<String>(client, url, token, request).await;
    log::info!("find ticket for sector {}: {:?}", miner, value);
    match value {
        Err(e) => Err(e),
        Ok(v) => {
            match v {
                None => Err(anyhow::anyhow!("ticket not found")),
                Some(v) => Ok(v)
            }
        }
    }
}